using System.Collections;
using DG.Tweening;
using UnityEngine;
using XLua;

public class PrettyGirlsChangeClothesComponent : MonoBehaviour
{
    [Header("头节点")]
    [SerializeField]
    private GameObject m_headGo;
    
    [Header("服装节点列表")]
    [SerializeField]
    private GameObject[] m_clothesList;
    
    [Header("服装网格列表")]
    [SerializeField]
    private GameObject[] m_clothesSkinnedMeshRendererList;
    
    [Header("服装明暗分别持续时间")]
    [SerializeField]
    private float m_effectDuration = 0.5f;

    private int m_currentClothesIndex = -1;

    private Material m_currentClothesMaterial;
    private Material m_targetClothesMaterial;
    private Tweener m_currentClothesTweener;
    private Tweener m_targetClothesTweener;

    private GameObject m_changeEffectGo;
    private ParticleSystem m_changeEffectPs;

    private Animator m_headAnimator;
    private Animator m_bodyAnimator;

    // 处理头、身体可能出现动画不同步的问题(概率极低，感觉是Unity的问题，如果检测到两边的动画归一化时间不一样的时候，就同步一下)
    private int m_frameCount = 0;
    
    private void OnDestroy()
    {
        if (m_currentClothesTweener != null)
        {
            m_currentClothesTweener.Kill();
        }
        if (m_targetClothesTweener != null)
        {
            m_targetClothesTweener.Kill();
        }
    }

    private void Update()
    {
        m_frameCount++;
        if (m_frameCount >= 10)
        {
            m_frameCount = 0;
            tryCheckSyncAnimState();
        }
    }

    private void tryCheckSyncAnimState()
    {
        if (m_headAnimator == null)
        {
            m_headAnimator = m_headGo.GetComponent<Animator>();
        }
        if (m_bodyAnimator == null)
        {
            m_bodyAnimator = m_clothesList[m_currentClothesIndex].GetComponent<Animator>();
        }
        if (m_headAnimator != null && m_bodyAnimator != null)
        {
            AnimatorStateInfo headStateInfo = m_headAnimator.GetCurrentAnimatorStateInfo(0);
            AnimatorStateInfo bodyStateInfo = m_bodyAnimator.GetCurrentAnimatorStateInfo(0);
            if (headStateInfo.shortNameHash != bodyStateInfo.shortNameHash || Mathf.Abs(headStateInfo.normalizedTime - bodyStateInfo.normalizedTime) > .1f)
            {
                m_bodyAnimator.Play(headStateInfo.shortNameHash, 0, headStateInfo.normalizedTime);
            }
        }
    }

    public void SetChangeEffectGo(GameObject effectGo)
    {
        m_changeEffectGo = effectGo;
        m_changeEffectPs = effectGo.GetComponent<ParticleSystem>();
    }

    public void ChangeClothes(int index, LuaFunction callback)
    {
        // 说明当前没有着装过，只是初始化服装，不做换装特效相关操作
        if (m_currentClothesIndex == -1)
        {
            SetClothesActive(index);
            m_currentClothesIndex = index;
            return;
        }

        m_bodyAnimator = null;
        m_currentClothesMaterial = m_clothesSkinnedMeshRendererList[m_currentClothesIndex].GetComponent<SkinnedMeshRenderer>().material;
        m_targetClothesMaterial = m_clothesSkinnedMeshRendererList[index].GetComponent<SkinnedMeshRenderer>().material;
        m_currentClothesIndex = index;
        if (m_currentClothesMaterial == null || m_targetClothesMaterial == null)
        {
            Debug.LogError("Material is null");
            return;
        }
        m_currentClothesTweener = m_currentClothesMaterial.DOFloat(1.0f, "_ClothChangeValue", m_effectDuration).OnComplete(() =>
        {
            m_currentClothesTweener.Kill();
            m_currentClothesTweener = null;
            m_currentClothesMaterial.SetFloat("_ClothChangeValue", 0);
            
            SetClothesActive(m_currentClothesIndex);
            m_changeEffectGo.SetActive(true);
            m_changeEffectPs.Play(true);
            
            tryCheckSyncAnimState();
            
            // 目标皮肤出现的那一刻是发亮的，慢慢地恢复成正常的衣服效果
            m_targetClothesMaterial.SetFloat("_ClothChangeValue", 1.0f);
            m_targetClothesTweener = m_targetClothesMaterial.DOFloat(0.0f, "_ClothChangeValue", m_effectDuration).OnComplete(() =>
            {
                m_targetClothesTweener.Kill();
                m_targetClothesTweener = null;
                StartCoroutine(DelayToStopEffect());
                callback?.Action();
            });
        });
    }
    
    private void SetClothesActive(int index)
    {
        for (int i = 0; i < m_clothesList.Length; i++)
        {
            m_clothesList[i].SetActive(i == index);
        }
    }

    private IEnumerator DelayToStopEffect()
    {
        float duration = m_changeEffectPs.main.duration - m_effectDuration;
        yield return new WaitForSeconds(duration);
        m_changeEffectGo.SetActive(false);
    }
}